#include <QtGui>
#include <QDeclarativeItem>
#include <QDeclarativeView>
#include <QDeclarativeEngine>
#include <QDeclarativeContext>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "playlistmodel.h"
#include "playlistlistmodel.h"
#include "dirutils.h"
#include "sortdialog.h"
#include "subscriptionlistmodel.h"
#include "urlutils.h"
#include "subscribedialog.h"
// #include "imageprovider.h"
#ifdef USE_OBJECTBROWSER
#include "qobjectbrowseraction.h"
#include "qobjecttree.h"
#endif

#ifdef Q_OS_SYMBIAN
#include "s60remote.h"
#endif


MainWindow* MainWindow::sm_instance = 0;

MainWindow* MainWindow::instance() {
    return sm_instance;
}

QDeclarativeItem* MainWindow::createFromResource(QString url) {
    QDeclarativeEngine *engine = ui->qmlView->engine();          /* Use QDeclarativeView created from Designer */

    QDeclarativeComponent component(engine, QUrl::fromUserInput(url));   /* Component is a factory for new Items. */
    if (component.isError()) {                                   /* An error exists in the QML? */
        foreach (QDeclarativeError error, component.errors())
            qDebug() << error.toString();                        /* Show all the errors. */
        abort();
    }
    QObject* myObject = component.create();                      /* Create QML Item from C++ side. */
    return qobject_cast<QDeclarativeItem*>(myObject);            /* Downcast to more useful type. */
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
  , m_position(0)
  , m_duration(0)
  , m_showElapsed(false)
  , m_state(QMediaPlayer::StoppedState)
  , m_player(0)
  , m_playList(0)
  , m_m3uListModel(0)
  , m_subscriptionListModel(0)
  , m_currentParentModel(0)
  , m_playListModel(0)
  , m_itemsListModel(0)
  , m_flickableView(0)
  , m_chosenFromQML(-1)
  , m_fastForward(false)
  , m_rewind(false)
{

    ui->setupUi(this);
    m_seekUpdates = true;
    QSettings s;
    sm_instance = this;
    s.setValue("playedsomething", false);

#ifdef Q_OS_SYMBIAN
    S60Remote* remote = new S60Remote(this);
    connect (remote, SIGNAL(volumeUp()), this, SLOT(on_actionVolumeUp_triggered()));
    connect (remote, SIGNAL(volumeDown()), this, SLOT(on_actionVolumeDown_triggered()));
    connect (remote, SIGNAL(playPause()), this, SLOT(on_actionPlay_Pause_triggered()));
    connect (remote, SIGNAL(next()), this, SLOT(on_actionNextTrack_triggered()));
    connect (remote, SIGNAL(previous()), this, SLOT(on_actionPreviousTrack_triggered()));
    connect (remote, SIGNAL(fastForwardPressed()), this, SLOT(on_nextButton_pressed()));
    connect (remote, SIGNAL(fastForwardReleased()), this, SLOT(on_nextButton_released()));
    connect (remote, SIGNAL(rewindPressed()), this, SLOT(on_previousButton_pressed()));
    connect (remote, SIGNAL(rewindReleased()), this, SLOT(on_previousButton_released()));
#endif
    ui->actionOpen->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon));
    ui->actionQuit->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
    ui->actionAdd_Playlist_Dir->setIcon(style()->standardIcon(QStyle::SP_DirOpenIcon));

    ui->actionVolumeUp->setIcon(style()->standardIcon(QStyle::SP_MediaVolume));

    // ui->menuView->addAction(ui->controlsDock->toggleViewAction());
    m_player = newPlayer();
    m_playList = new QMediaPlaylist(this);
    connect (m_playList, SIGNAL(currentIndexChanged(int)),
             this, SLOT(checkQueue()));

    m_queue = new QMediaPlaylist(this);
    connect (m_queue, SIGNAL(currentIndexChanged(int)),
             this, SLOT(updateQueue(int)));
    m_player->setPlaylist(m_playList);
    m_playListModel = new PlaylistModel(this);
    m_playListModel->setPlaylist(m_playList);

    // Podcast subscriptions and episodes:
    m_itemsListModel = new ItemsListModel(this);
    m_subscriptionListModel = new SubscriptionListModel(this);

    // do we need a bidirectional connection like this?
    connect (m_subscriptionListModel, SIGNAL(subscriptionUpdated(Subscription*)),
             m_itemsListModel, SLOT(refreshIfNecessary(Subscription*)));
    connect (m_itemsListModel, SIGNAL(subscriptionUpdated(Subscription*)),
             m_subscriptionListModel, SLOT(updateSubscription(Subscription*)));

    // parent list model:
    s.setValue("cleanexit", false);
    m_m3uListModel = new PlayListListModel(this);

    m_currentParentModel = m_m3uListModel;

    QString rootPath = s.value("songsdir", QDir::currentPath()).toString();

    connect(ui->seekSlider, SIGNAL(sliderPressed()), this, SLOT(disableSeekUpdates()));
    connect(ui->seekSlider, SIGNAL(sliderReleased()), this, SLOT(enableSeekUpdates()));

    connect(m_playList, SIGNAL(currentIndexChanged(int)), this, SLOT(updateNowPlaying(int)));

    QDeclarativeEngine *engine = ui->qmlView->engine();         /* Use QDeclarativeView created from Designer */
    // engine->addImageProvider("activity", new ImageProvider());
    QDeclarativeContext* context = engine->rootContext();       /* Get root context */

    // Make C++ objects available from QML side:
    context->setContextProperty("playListModel", m_playListModel);
    context->setContextProperty("playQueue", m_queue);
    context->setContextProperty("itemsListModel", m_itemsListModel);
    context->setContextProperty("m3uListModel", m_m3uListModel);
    context->setContextProperty("mainWindow", this);

    // load main QML interface:
    m_flickableView = createFromResource("qrc:/FlickableViews.qml");
    ui->qmlView->scene()->addItem(m_flickableView); /* Use QGraphicsView API to add item to scene */

    // QObject findChild() to get pointers to some QML objects that were created above
    m_playListView = m_flickableView->findChild<QDeclarativeItem*>("playListView");
    m_parentListView = m_flickableView->findChild<QDeclarativeItem*>("parentListView");  
    m_mainMenu = m_flickableView->findChild<QDeclarativeItem*>("mainMenu");
    m_subscriptionView = m_flickableView->findChild<QDeclarativeItem*>("subscriptionView");

    // find actual object with name flickableView
    m_flickableView = m_flickableView->findChild<QDeclarativeItem*>("flickableView");
    m_helpDialog = createFromResource("qrc:/HelpDialog.qml");
    ui->qmlView->scene()->addItem(m_helpDialog);
    m_helpDialog->setProperty("visible", false);
    restoreSettings();

//     showPlayList();

#ifdef USE_OBJECTBROWSER
    ui->menuView->addAction(new QObjectBrowserAction(this));
    QObjectTreeModel::addExtraObject(m_flickableView);
    QObjectTreeModel::addExtraObject(context);
#endif

    connect (ui->actionControls, SIGNAL(toggled(bool)), this, SIGNAL(qmlResized()), Qt::QueuedConnection);
    QTimer::singleShot(2000, this, SIGNAL(qmlResized()));

}

QMediaPlayer* MainWindow::newPlayer() {
    QMediaPlayer* retval = new QMediaPlayer(this);
    connect(retval, SIGNAL(stateChanged(QMediaPlayer::State)),
        this, SLOT(updateState(QMediaPlayer::State)));
    connect(retval, SIGNAL(volumeChanged(int)), ui->volumeSlider, SLOT(setValue(int)));
    connect(retval, SIGNAL(durationChanged(qint64)), this, SLOT(updateDurationInfo(qint64)));
    connect(retval, SIGNAL(positionChanged(qint64)), this, SLOT(updatePositionInfo(qint64)));
    connect(retval, SIGNAL(metaDataChanged()), this, SLOT(updateTrackInfo()));
    connect(retval, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
            this, SLOT(statusChanged(QMediaPlayer::MediaStatus)));
    connect(retval, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int)));
    connect(retval, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(displayErrorMessage()));

    connect(ui->volumeSlider, SIGNAL(sliderMoved(int)), retval, SLOT(setVolume(int)));
    return retval;

}


void MainWindow::closeEvent(QCloseEvent *) {
    on_actionQuit_triggered();
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::changeEvent(QEvent *e) {
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::on_actionQuit_triggered() {
    saveSettings();
    qApp->quit();
}

void MainWindow::on_actionOpen_triggered() {
    QSettings s;
    QString songsDir = s.value("songsdir", QDir::currentPath()).toString();

#ifdef Q_WS_MAEMO_5
    QStringList fileNames;
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Files"), songsDir);
    if (!fileName.isEmpty())
        fileNames << fileName;
#else
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open Files"), songsDir);
#endif
    if (!fileNames.isEmpty()) {
        songsDir = fileNames[0];
        s.setValue("songsdir", songsDir);
        addToPlaylist(fileNames);
    }
    showPlayList();
}


void MainWindow::saveSettings() {
    QSettings s;
    s.setValue("cleanexit", true);
    s.setValue("state", saveState());
    s.setValue("volume", m_player->volume());
    // TODO: Write current playlist to temporary file.
    
    
}

void MainWindow::restoreSettings() {
    QSettings s;
    QVariant v = s.value("state");

    if (!v.isNull()) {
        QByteArray barr = v.toByteArray();
        restoreState(barr);
    }
    int vol = s.value("volume", m_player->volume()).toInt();
    ui->volumeSlider->setValue(vol);
    m_player->setVolume(vol);

    QString cm3u = currentM3u();
    QStringList presets;
    presets << "Menu" << "Subscriptions" << "Playlists";
    QString showOption = s.value("show").toString();
    if (showOption == "Now Playing") {
        openPlayList(currentM3u());
        int currentRow = s.value("current.row").toInt();
        m_playList->setCurrentIndex(currentRow);
        int idx = m_m3uListModel->indexOf(currentM3u());
        if (idx != -1)  {
            m_parentListView->setProperty("currentIndex", idx);
        }
    }
    else setShowOption(showOption);

    bool volumeVisible = s.value("volume.visible", false).toBool();
    ui->volumeWidget_2->setVisible(volumeVisible);
    ui->actionVolumeToggle->setChecked(volumeVisible);
}

void MainWindow::addToPlaylist(const QStringList& fileNames) {

    foreach (QString const &argument, fileNames) {
        QFileInfo fileInfo(argument);
        if (fileInfo.exists()) {

            QUrl url = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
            if (fileInfo.suffix().toLower() == QLatin1String("m3u")) {
                m_playList->load(url);
            } else {
                m_playList->addMedia(url);
            }
        } else { // See if it is a url?
            QUrl url = QUrl::fromUserInput(argument);
            if (url.isValid()) {
                m_playList->addMedia(url);
            }
        }
    }
    m_playListModel->fetchAll();
}



void MainWindow::statusChanged(QMediaPlayer::MediaStatus status) {
    handleCursor(status);

    // handle status message
    switch (status) {
    case QMediaPlayer::UnknownMediaStatus:
    case QMediaPlayer::NoMedia:
    case QMediaPlayer::LoadedMedia:
    case QMediaPlayer::BufferingMedia:
    case QMediaPlayer::BufferedMedia:
        setStatusInfo(QString());
        break;
    case QMediaPlayer::LoadingMedia:
        setStatusInfo(tr("Loading..."));
        break;
    case QMediaPlayer::StalledMedia:
        setStatusInfo(tr("Media Stalled"));
        break;
    case QMediaPlayer::EndOfMedia:
        if (m_player->playlist() == m_queue) {
            m_player->setPlaylist(m_playList);
            m_queue->clear();
            m_player->play();
        } else
            QApplication::alert(this);
        break;
    case QMediaPlayer::InvalidMedia:
        displayErrorMessage();

        break;
    }
}

void MainWindow::handleCursor(QMediaPlayer::MediaStatus status) {
#ifndef QT_NO_CURSOR
    if( status == QMediaPlayer::LoadingMedia ||
        status == QMediaPlayer::BufferingMedia ||
        status == QMediaPlayer::StalledMedia)
        setCursor(QCursor(Qt::BusyCursor));
    else
        unsetCursor();
#endif
}

void MainWindow::bufferingProgress(int progress) {
    setStatusInfo(tr("Buffering %4%").arg(progress));
}

void MainWindow::setTrackInfo(const QString &info) {
    m_trackInfo = info;
    if (!m_statusInfo.isEmpty())
        setWindowTitle(QString("%1 | %2")
            .arg(m_trackInfo).arg(m_statusInfo));
    else
        if (!m_trackInfo.isEmpty())
            setWindowTitle(m_trackInfo);
}

void MainWindow::setStatusInfo(const QString &info) {
    m_statusInfo = info;
    if (!m_statusInfo.isEmpty())
        statusBar()->showMessage(QString("%1 | %2")
            .arg(m_trackInfo).arg(m_statusInfo));
    else
        statusBar()->showMessage(m_trackInfo);
}


void MainWindow::displayErrorMessage() {
    setStatusInfo(m_player->errorString());

}

void MainWindow::on_playButton_clicked() {
    m_state = m_player->state();
    qDebug() << "Play:  " << m_player->media().canonicalUrl();
    if (m_state == QMediaPlayer::PlayingState)
        m_player->pause();
    else
        m_player->play();
}

void MainWindow::playQmlSelected() {
    if (m_player->playlist() != m_playListModel->playlist())
        m_player->setPlaylist(m_playListModel->playlist());

    if (m_chosenFromQML != -1)  {
        m_player->playlist()->setCurrentIndex(m_chosenFromQML);
        updateNowPlaying(m_chosenFromQML);
        qDebug() << "playQML: " << m_player->playlist()->media(m_chosenFromQML).canonicalUrl();
    }
    m_player->play();
}

void MainWindow::clickEpisode(int i) {
    QModelIndex idx =m_itemsListModel->index(i, 0);
    int statusVal = m_itemsListModel->data(idx, ItemsListModel::StatusRole).toInt();
    if (statusVal == Download::Complete) {
        QString path = m_itemsListModel->data(idx, ItemsListModel::PathRole).toString();
        QUrl url = QUrl::fromLocalFile(path);
        m_player->setMedia(url);
        m_player->play();
        return;
    }
    m_itemsListModel->downloadEpisode(i);
}

void MainWindow::updateState(QMediaPlayer::State state) {
    m_state = state;
    switch (state) {
        case QMediaPlayer::StoppedState:
        case QMediaPlayer::PausedState:

            ui->playButton->setToolTip(tr("Play"));
            ui->playButton->setChecked(false);
            break;
        case QMediaPlayer::PlayingState:

            ui->playButton->setToolTip(tr("Pause"));
            ui->playButton->setChecked(true);
            break;

    }
}



void MainWindow::jump(const QModelIndex &index)
{
    if (index.isValid()) {

        if (m_player->playlist() != m_playListModel->playlist()) {
            m_player->setPlaylist(m_playListModel->playlist());
        }
        m_player->playlist()->setCurrentIndex(index.row());
        m_player->play();
    }
}

void MainWindow::updateNowPlaying(int currentIndex) {
    if (m_player->playlist() != m_playListModel->playlist()) {
        m_playListModel->setPlaylist(m_player->playlist());
    }
    if ((m_playListModel->rowCount() > 0) && (m_playListModel->playlist() == m_playList)) {
        m_playListView->setProperty("currentIndex", currentIndex);
        QSettings s;
        s.setValue("current.row", currentIndex);
    }
}

void MainWindow::updatePositionInfo(qint64 msecs) {
    m_position = msecs / 1000;
    if (m_seekUpdates)
        ui->seekSlider->setValue(m_position);
    updateStatusInfo();
}

void MainWindow::updateStatusInfo() {
    QString tStr;
    if (m_position || m_duration) {
        QString format = "mm:ss";
        QTime t;
        if (m_showElapsed) {
            int secs = m_position;
            t = t.addSecs(secs);
            QString format = "mm:ss";
            if (secs > 3600)
                format = "hh:mm:ss";
            tStr = t.toString(format);
        }
        else {
            int secs = m_duration - m_position;
            t = t.addSecs(secs);
            if (secs > 3600)
                format = "hh:mm:ss";
            tStr = t.toString(format);
        }
    }
    if (!tStr.isEmpty()) {
        setStatusInfo(QString("[%1]").arg(tStr));
        ui->durationButton->setText(tStr);
    }
}

void MainWindow::updateDurationInfo(qint64 msecs)
{
    m_duration = msecs / 1000;
    ui->seekSlider->setMaximum(m_duration);
    updateTrackInfo();
}

void MainWindow::updateTrackInfo() {
    if (m_player->isMetaDataAvailable()) {
        QSettings s;
        s.setValue("playedsomething", true);

        setTrackInfo(QString("%2 - %1")
                .arg(m_player->metaData(QtMultimediaKit::AlbumArtist).toString())
                .arg(m_player->metaData(QtMultimediaKit::Title).toString()));
//        QVariant v = m_player->metaData(QtMultimediaKit::CoverArtImage);
    }
    else {
        QUrl url = m_player->media().canonicalUrl();
        setTrackInfo(UrlUtils::baseName(url));
    }
    QString tStr;
    if (m_position || m_duration) {
        QTime remaining(0,0,0,0);
        int secs = m_duration - m_position;
        remaining = remaining.addSecs(secs);

        QString format = "mm:ss";
        if (m_duration > 3600)
            format = "hh:mm:ss";
        tStr = remaining.toString(format);
        setStatusInfo(tStr);
    }
}


void MainWindow::openPlayListI(int row) {
    m_parentListView->setProperty("currentIndex", row);

    QString path = m_currentParentModel->data(
            m_currentParentModel->index(row, 0), PlayListListModel::PathRole).toString();
    if (m_currentParentModel == m_m3uListModel)
        openPlayList(path);
    else {
        Subscription& s = m_subscriptionListModel->subscription(row);
//        qDebug() << "Subscription: " << s.name;

        setM3uTitle(s.name);
        m_itemsListModel->setSubscripton(&s);
        m_flickableView->setProperty("state", "Episodes");

    }

}

void MainWindow::openPlayList(QString path) {
    QSettings s;
    s.setValue("cleanexit", false);
    QFileInfo fi(path);
    QUrl url = QUrl::fromUserInput(path);
    if (fi.exists()) {
        url = QUrl::fromLocalFile(path);
    }
    else if (url.isValid()) {
        path = UrlUtils::toLocalFile(url);
        fi = QFileInfo(path);
    }

    setM3uTitle(fi.completeBaseName());
    if (m_playListModel->playlist() != m_playList)
        m_playListModel->setPlaylist(m_playList);
    m_playListModel->clear();
    if (fi.isDir()) {
        foreach (QString p, DirUtils::songsInDir(path)) {
            QUrl url = QUrl::fromLocalFile(p);
            m_playList->addMedia(url);
        }
    }
    else m_playList->load(url);
    m_playListModel->fetchAll();
    m_currentPlaylist = fi.absoluteFilePath();

    // ui->showCombo->setItemText(NowPlaying, UrlUtils::baseName(url));
    // ui->showCombo->setCurrentIndex(NowPlaying);
    if (m_player->playlist() != m_queue) {
        m_player->setPlaylist(m_playList);
    }
    setShowOption("Now Playing");
    setCurrentM3u(m_currentPlaylist);
    showPlayList();
    emit playListChanged();

    QTimer::singleShot(2000, this, SLOT(restoreSortedOrder()));
}

void MainWindow::jumpAhead() {
    m_fastForward = true;
    qint64 pos = m_player->position();
    QTime now = QTime::currentTime();
    int msecs = (5 * m_pressedTime.msecsTo(now)) + 10000;
    pos += msecs;
    qDebug() << "Skip " << msecs << " msecs. ";
    m_player->setPosition(pos);
}

void MainWindow::jumpBackward() {
    m_rewind = true;    
    QTime now = QTime::currentTime();
    int msecs = (5 * m_pressedTime.msecsTo(now)) + 10000;
    qint64 pos = m_player->position();
    pos -= msecs;
    if (pos < 0) pos = 0;
    m_player->setPosition(pos);
}

void MainWindow::seek(int seconds) {
    m_player->setPosition(seconds * 1000);
}

void MainWindow::on_previousButton_clicked() {
    if (m_rewind) m_rewind = false;
    else on_actionPreviousTrack_triggered();
}

void MainWindow::on_previousButton_pressed() {
    connect (&m_rewindTimer, SIGNAL(timeout()),
             this, SLOT(jumpBackward()), Qt::UniqueConnection);
    m_rewindTimer.start(1200);
    m_pressedTime = QTime::currentTime();
}

void MainWindow::on_previousButton_released() {
    m_rewindTimer.stop();
}

void MainWindow::on_nextButton_clicked() {
    if (m_fastForward) m_fastForward = false;
        else on_actionNextTrack_triggered();
}

void MainWindow::on_nextButton_pressed()
{
    connect (&m_fastForwardTimer, SIGNAL(timeout()),
             this, SLOT(jumpAhead()), Qt::UniqueConnection);
    m_fastForwardTimer.start(1200);
    m_pressedTime = QTime::currentTime();
}

void MainWindow::on_nextButton_released()
{
    m_fastForwardTimer.stop();
}

void MainWindow::on_actionPlay_Pause_triggered() {
    on_playButton_clicked();
}

void MainWindow::on_actionAbout_triggered() {
    QMessageBox::information(this, tr("About %1").arg(qApp->applicationName()),
           tr("This is a small-screened touch-friendly application that loads and plays standard m3u playlists. "
              "The main window, menus, and buttons are based on QMainWindow and QWidget. "
              "Lists are organized in a Flickable, responding to flicks between lists (horizontal flicking) or up and down the list (vertical flicking). "
              "You can subscribe to podcasts and play tracks from folders. Uses Qt Mobility 1.2. "),
              QMessageBox::Ok, QMessageBox::Ok);
}

void MainWindow::on_actionAboutQt_triggered() {
    qApp->aboutQt();
}

void MainWindow::on_actionVolumeToggle_toggled(bool visible ) {
    QSettings s;
    s.setValue("volume.visible", visible);
    ui->volumeWidget_2->setVisible(visible);
    emit qmlResized();
}


void MainWindow::on_actionVolumeUp_triggered()
{
    int step = ui->volumeSlider->pageStep();
    int oldValue = m_player->volume();
    m_player->setVolume(oldValue + step);
    showVolumeSliderBriefly();
}

void MainWindow::showVolumeSliderBriefly() {
    if (ui->volumeWidget_2->isVisible()) return;
    ui->volumeWidget_2->setVisible(true);
    QTimer::singleShot(3000, ui->volumeWidget_2, SLOT(hide()));

}

void MainWindow::on_actionVolumeDown_triggered()
{
    int step = ui->volumeSlider->pageStep();
    int oldValue = m_player->volume();
    m_player->setVolume(oldValue - step);
    showVolumeSliderBriefly();
}

void MainWindow::on_actionNextTrack_triggered()
{
    if (m_player->playlist() == m_queue) {
          m_queue->removeMedia(0, 0);
          emit playListChanged();
          if (!m_queue->isEmpty()) {
              m_queue->setCurrentIndex(0);
              setM3uTitle("Queue");
              m_playListModel->setPlaylist(m_queue);
          }
          else {
              m_playListModel->setPlaylist(m_playList);
              m_player->setPlaylist(m_playList);             
          }

          m_player->play();
          return;
    }
    else {
        if (m_queue->mediaCount() > 1) {
            m_queue->setCurrentIndex(0);
            setM3uTitle("Queue");
            m_player->setPlaylist(m_queue);
            m_playListModel->setPlaylist(m_queue);
            return;
        }
    }
    if (m_player->playlist() != m_playListModel->playlist()) {
        toggleQueue();
    }
    int idx = m_playList->currentIndex();
    int max = m_playList->mediaCount();
    if (idx < max-1) {
        idx++;
        m_playList->setCurrentIndex(idx);
        m_player->play();
    }
}

void MainWindow::on_actionPreviousTrack_triggered()
{
    int idx = m_playList->currentIndex();
    if (idx > 0) idx --;
    m_playList->setCurrentIndex(idx);
    m_player->play();


}


void MainWindow::resizeEvent(QResizeEvent *e) {
    QMainWindow::resizeEvent(e);
    emit qmlResized();
}

int MainWindow::qmlWidth() const {
    return ui->qmlView->width();
}

int MainWindow::qmlHeight() const {

    int retval = ui->qmlView->height();
    if (retval < 100) return 100;
    return retval;
}


void MainWindow::on_actionAdd_Playlist_Dir_triggered()
{
    QSettings s;
    QString songsDir = s.value("songsdir", QDir::currentPath()).toString();
    QString newDir = QFileDialog::getExistingDirectory(this, tr("Add M3u Folder"), songsDir);
    if (newDir.isEmpty()) return;
    s.setValue("songsdir", newDir);

    m_m3uListModel->addM3uDirectory(newDir);

}

void MainWindow::on_actionClear_Settings_triggered()
{
    QSettings s;
    s.clear();
    m_m3uListModel->clear();
}

void MainWindow::on_actionAdd_Song_Dir_triggered()
{
    QSettings s;

    QString songsDir = s.value("songsdir", QDir::currentPath()).toString();
    QString newDir = QFileDialog::getExistingDirectory(this, tr("Add Tracks Dir"), songsDir);
    if (newDir.isEmpty()) return;
    s.setValue("songsdir", newDir);
    m_m3uListModel->addSongDirectory(newDir);
}

void MainWindow::setChosenFromQML(int i) {
//    qDebug() << "chosen from QML: " << i;
    if (i != m_chosenFromQML) {
        if (i != -1) m_chosenFromQML = i;
        emit chosenFromQMLChanged();
    }
    m_playListModel->fetch(i);
}

void MainWindow::on_actionShuffle_triggered()
{
    m_playListModel->shuffle();
}


void MainWindow::on_actionSet_Podcast_Dir_triggered()
{
    QSettings s;
    QString songsDir = s.value("podcastdir", s.value("songsdir", QDir::currentPath())).toString();
    QString newDir = QFileDialog::getExistingDirectory(this, tr("Choose Podcast Folder"), songsDir);
    if (newDir.isEmpty()) return;
    s.setValue("podcastdir", newDir);
    if (songsDir == QDir::currentPath())
        s.setValue("songsdir", newDir);
    m_m3uListModel->scanForSongDirs(newDir);
}


void MainWindow::on_actionSort_Playlist_triggered()
{
    QSettings s;
    SortDialog sd;
    if (!m_playListModel->isFetched()) {
        m_playListModel->fetchAll();
    }

    if (sd.exec() == QDialog::Accepted) {
        SortDialog::Option o = sd.option();
        sortByOption(o);
        s.setValue("sorting/" + m_currentPlaylist, o);
    }
}

void MainWindow::sortByOption(SortDialog::Option o) {
    if (o == SortDialog::None) return;
    if (!m_playListModel->isFetched()) {
        m_playListModel->fetchAll();
        return;
    }
    qDebug() << "SortByOption: " << o;
    switch (o) {
        case SortDialog::Recent:
            m_playListModel->sortByRole(PlaylistModel::LastModifiedRole);
            break;
        case SortDialog::Album:
            m_playListModel->sortByRole(PlaylistModel::AlbumRole);
            break;
        case SortDialog::Artist:
            m_playListModel->sortByRole(PlaylistModel::ArtistRole);
            break;
        case SortDialog::Title:
            m_playListModel->sortByRole(PlaylistModel::NameRole);
        case SortDialog::None:
            break;
    }
}

void MainWindow::showSubscriptions() {
    setM3uTitle("Subscriptions");
    if (m_currentParentModel != m_subscriptionListModel) {
        m_currentParentModel = m_subscriptionListModel;
        QDeclarativeEngine *engine = ui->qmlView->engine();
        QDeclarativeContext* context = engine->rootContext();
        context->setContextProperty("m3uListModel", m_currentParentModel);
    }
}

void MainWindow::hideSubscriptions() {
    if (m_currentParentModel != m_m3uListModel) {
        m_currentParentModel = m_m3uListModel;
        QDeclarativeEngine *engine = ui->qmlView->engine();
        QDeclarativeContext* context = engine->rootContext();
        context->setContextProperty("m3uListModel", m_currentParentModel);
    }
}

void MainWindow::showPlayList() {
    m_flickableView->setProperty("state", "Playlist");
    QString m3u = currentM3u();
    setM3uTitle(m3u);
}
void MainWindow::showParentList() {

    if (m_flickableView == 0) return;
    m_flickableView->setProperty("state", "Parentlist");
//    qDebug() << "State after: " << m_flickableView->property("state").toString();
}

QString MainWindow::showOption() const {
    QSettings s;
    return s.value("show").toString();
}

void MainWindow::setShowOption(QString showOption) {

    QSettings s;
    s.setValue("show", showOption);
    setM3uTitle(showOption);
    if ((showOption == "Subscriptions") || showOption == "Episodes") {
        showSubscriptions();
        if (m_subscriptionListModel->rowCount()== 0) on_actionAddFeed_triggered();
    }
    else hideSubscriptions();


    if (m_currentParentModel == m_m3uListModel) {
        m_m3uListModel->restoreFromSettings();
    }
    if (showOption == "Now Playing") {
        showPlayList();
    }
    else {
        showParentList();
        if (m_m3uListModel->rowCount() == 0) {
            if (showOption == "Playlists") on_actionAdd_Playlist_Dir_triggered();
            else if (showOption == "Song Folders") on_actionAdd_Song_Dir_triggered();
        }
    }
    emit showOptionChanged();
}

void MainWindow::restoreSortedOrder() {
    QSettings s;
    SortDialog::Option o = (SortDialog::Option) s.value("sorting/" + m_currentPlaylist, SortDialog::None).toInt();
    sortByOption(o);

    int currentRow = s.value("current.row", -1).toInt();
    if (currentRow > -1) {
        m_playList->setCurrentIndex(currentRow);
    }
}

void MainWindow::on_reloadButton_clicked()
{
    if (m_subscriptionListModel == 0) return;
    QString state = m_flickableView->property("state").toString();
    if (showOption() == "Subscriptions") {
        m_subscriptionListModel->reload();
    }
    else if (state == "Episodes") {
        int i= m_parentListView->property("currentIndex").toInt();
        m_subscriptionListModel->reload(i);
    }
    else if (!m_currentPlaylist.isEmpty()) {
        openPlayList(m_currentPlaylist);
        return;
    }
}

void MainWindow::on_actionAddFeed_triggered()
{
    SubscribeDialog sd(this);
    if (sd.exec() == QDialog::Accepted) {
        m_subscriptionListModel->subscribe(sd.name(), sd.url());
    }
}

void MainWindow::setCurrentM3u(QString m3u) {
    QSettings s;
    s.setValue("current.m3u", m3u);
    setM3uTitle(m3u);
    emit currentM3uChanged();
}

QString MainWindow::currentM3u() const {
    QSettings s;
    return s.value("current.m3u", "Menu").toString();
}

void MainWindow::setM3uTitle(QString t) {
    if (t.contains("/"))
        t = UrlUtils::baseName(t);
    m_m3utitle = t;
    setWindowTitle(t);
    emit m3uTitleChanged();
}

QString MainWindow::m3uTitle() const {
    return m_m3utitle;
}
void MainWindow::close() {
    int row = m_parentListView->property("currentIndex").toInt();
    QModelIndex midx = m_currentParentModel->index(row, 0);

    if (m_currentParentModel == m_m3uListModel) {
        QString fileName = m_currentParentModel->data(midx, Qt::EditRole).toString();
        if (QMessageBox::question(this, "Close Playlist?", tr("Close Playlist %1?").arg(fileName), QMessageBox::Yes, QMessageBox::No)  == QMessageBox::Yes) {
            m_m3uListModel->closePlaylist(fileName);
            showParentList();
        }
    }
    else {
        QString name = m_currentParentModel->data(midx, Qt::DisplayRole).toString();
        if (QMessageBox::question(this, "Unsubscribe Podcast?", tr("Unsubscribe to %1?").arg(name), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
            m_subscriptionListModel->removeRow(row);
            showParentList();
        }
    }

}

void MainWindow::toggleQueue() {
    if (m_playListModel->playlist() == m_playList) {
        if (m_queue->mediaCount() > 0) {
            m_playListModel->setPlaylist(m_queue);
            setM3uTitle("Queue");
            m_playListView->setProperty("currentIndex", m_queue->currentIndex());
            // setShowOption("Queue");
        }
    }
    else if (!m_playList->isEmpty()) {
        setM3uTitle( UrlUtils::baseName(m_currentPlaylist));
        m_playListModel->setPlaylist(m_playList);
        m_playListView->setProperty("currentIndex", m_playList->currentIndex());
        setShowOption("Now Playing");
    }
    m_playListView->setProperty("interactive", true);
//     showPlayList();
}


int MainWindow::positionInQueue(QString urlString) {
    int inQ = m_queue->mediaCount();
    QUrl url(urlString);
    for (int i=0; i< inQ; ++i) {
        QString u2 = m_queue->media(i).canonicalUrl().toString();
        if (u2 == urlString) return i;
    }
    return -1;
}

void MainWindow::enqueue(QString urlString) {
    QFileInfo fi(urlString);
    QUrl url = QUrl::fromUserInput(urlString);
    if (fi.exists()) {
        url = QUrl::fromLocalFile(urlString);
        urlString = url.toString();
    }
    int piq = positionInQueue(urlString);
    if (piq == -1) {
        m_queue->addMedia(url);
        if (m_playList->mediaCount() == 0) {
            m_playListModel->setPlaylist(m_queue);
        }
        if (!m_player->state() == QMediaPlayer::PlayingState) {
            m_player->setPlaylist(m_queue);
            m_player->play();
        }
    }
    else {
        m_queue->removeMedia(piq, piq);
    }
    emit playListChanged();
}

bool MainWindow::isQueueEmpty() const {
    return m_queue->isEmpty();
}

void MainWindow::checkQueue() {
    if (!m_queue->isEmpty() && (m_player->playlist() != m_queue)) {
        m_player->setPlaylist(m_queue);
        m_queue->setCurrentIndex(0);
        m_player->play();
    }
}

void MainWindow::updateQueue(int i) {
    if (i > 0) {
        m_queue->removeMedia(0, i-1);
        m_queue->setCurrentIndex(0);
        m_player->play();
    }
    if (i == -1) {
        m_queue->clear();
    }
    if (m_queue->isEmpty()) {
        m_player->setPlaylist(m_playList);
        m_player->play();
    }
}

bool MainWindow::isPlayListEmpty() const {
    return m_playList->isEmpty();
}

void MainWindow::disableSeekUpdates() {
    m_seekUpdates = false;
}
void MainWindow::enableSeekUpdates() {
    seek(ui->seekSlider->sliderPosition());
    m_seekUpdates = true;
}



void MainWindow::on_durationButton_clicked(bool checked)
{
    m_showElapsed = checked;
}

void MainWindow::on_actionHelp_triggered()
{
    m_helpDialog->setVisible(true);
}
